package optimizers.ganeat.square;

import java.awt.GridLayout;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.swing.JPanel;

import optimizers.commons.GAConstants;
import optimizers.commons.RunConfig;
import optimizers.ganeat.Connection;
import optimizers.ganeat.Constants;
import optimizers.ganeat.Individual;
import optimizers.ganeat.Node;
import optimizers.ganeat.math.ConstantsMath;
import optimizers.ganeat.sin.ConstantsSin;
import optimizers.ganeat.sin.IndividualSin;
import runconfiguration.SquareConfiguration;

import util.MyUtil;
import visualization.PlotExpData;

import model.InhibitingSequence;
import model.Input;
import model.InvalidConcentrationException;
import model.InvalidKException;
import model.OligoSystemComplex;
import model.OligoSystemGeneral;
import model.Sequence;
import model.SimpleSequence;
import model.Template;

import fitness.BistableResult;
import fitness.FitnessResult;
import fitness.NANDResult;
import fitness.SquareFitness;

public class IndividualSquare extends IndividualSin {

	/**
	 * 
	 */
	private static final long serialVersionUID = 5215001072434783056L;
	protected double[] sequenceConcentration = new double[2];

	public IndividualSquare(Map<String, Integer> innovations,
			Map<String, String> nodeNames, int geneIndex, int indivIndex,
			RunConfig config) {
		super(innovations, nodeNames, geneIndex, indivIndex, config);
		// TODO Auto-generated constructor stub
	}

	public IndividualSquare(Map<String, Integer> innovations,
			Map<String, String> nodeNames, int geneIndex, int indivIndex,
			RunConfig config, String string) {
		super(innovations, nodeNames, geneIndex, indivIndex, config, string);
	}

	@Override
	protected String getGoalStringName() {
		return "SquareT";
	}

	@Override
	public JPanel displayTimeSeries(String title) {
		JPanel result = new JPanel();
		OligoSystemGeneral oligoModel = getOligoModel();
		int output = 0;
		if (oligoModel.nameToInt.get("a") != null) {
			output = oligoModel.nameToInt.get("a");
		}
		double[][] data1 = oligoModel.getTimeSeriesComplexModel();
		int firstPeak = MyUtil.getFirstPeak(data1[output],
				ConstantsSin.skipTime);
		double[][] data2 = new double[2][data1[0].length];
		String[] seqNames = new String[] { "a", "target" };
		double maxY = Double.MIN_VALUE;
		for (int j = 0; j < data1[0].length; j++) {
			data2[0][j] = data1[output][j];
			if (j >= firstPeak
					&& j <= firstPeak + ConstantsSin.period
							* ConstantsSin.numberofperiods) {
				SquareFitness squareEvaluator = new SquareFitness();
				data2[1][j] = squareEvaluator.goal(j, firstPeak);
				if (maxY < data2[1][j]) maxY = data2[1][j];
			}
		}
		final PlotExpData demo1 = new PlotExpData(title, data2, seqNames,
				"Input (nM)", "Output (nM)", 0, 1, false, maxY * 6, 10);
		result.add(demo1);
		return (result);
	}
	
	@Override
	public JPanel displayTimeSeriesWithButton() {
		// TODO Auto-generated method stub
		return displayTimeSeries();
	}

	@Override
	public JPanel displayTimeSeries() {
		JPanel result = new JPanel();
		OligoSystemGeneral oligoModel = getOligoModel();
		int output = 0;
		if (oligoModel.nameToInt.get("a") != null) {
			output = oligoModel.nameToInt.get("a");
		}
		double[][] data1 = oligoModel.getTimeSeriesComplexModel();
		int firstPeak = MyUtil.getFirstPeak(data1[output],
				ConstantsSin.skipTime);
		double[][] data2 = new double[2][data1[0].length];
		String[] seqNames = new String[] { "a", "target" };
		double maxY = Double.MIN_VALUE;
		for (int j = 0; j < data1[0].length; j++) {
			data2[0][j] = data1[output][j];
			if (j >= firstPeak
					&& j <= firstPeak + ConstantsSin.period
							* ConstantsSin.numberofperiods) {
				SquareFitness squareEvaluator = (SquareFitness) config.evaluator;
				data2[1][j] = squareEvaluator.goal(j, firstPeak);
				if (maxY < data2[1][j])
					maxY = data2[1][j];
			}
		}
		final PlotExpData demo1 = new PlotExpData("Generation "
				+ this.generationIndex + " Index " + this.individualIndex,
				data2, seqNames, "Input (nM)", "Output (nM)",
				0, 1, false, maxY * 6, 10);
		result.add(demo1);
		return (result);
	}
}
